/**
 * 
 */
package cn.edu.jlu.grid.vjm;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @author whb
 *
 */
public class VJobExecute {
	private static VJobExecute inst = null;
	
	private VJobGateKeeperServer gkServer = null;
	private VJobMessageCenter msgCenter = null;

	private InetAddress vjcAddress = null;
	private int vjcPort = 0;
	
	private int reservationHandler = -1;
	private int requestId = -1;
	
	private int vjobId = -1;

	private VJobExecute() {
		gkServer = new VJobGateKeeperServer();
		msgCenter = new VJobMessageCenter();
	}
	
	public static void init() {
		if(inst == null) inst = new VJobExecute();
	}
	
	public static VJobExecute getInstance() {
		if(inst == null) init();
		return inst;
	}
	
	public InetAddress getVJCAddress() {
		return vjcAddress;
	}
	public int getVJCPort() {
		return vjcPort;
	}
	public void setVJCAddress(InetAddress addr) {
		vjcAddress = addr;
	}
	public void setVJCPort(int p) {
		vjcPort = p;
	}
	public int getReservationHandler() {
		return reservationHandler;
	}
	public void setReservationHandler(int handler) {
		this.reservationHandler = handler;
	}
	public int getRequestId() {
		return requestId;
	}
	public void setRequestId(int id) {
		requestId = id;
	}
	
	public InetAddress getLocalAddress() {
		//return msgCenter.getAddress();
		InetAddress addr = null;
		try { addr = InetAddress.getLocalHost(); } catch(Exception e){}
		return addr;
	}
	public int getLocalPort() {
		return msgCenter.getPort();
	}
	
	public int getVjobId(){
		return this.vjobId;
	}
	public void setVjobId(int id) {
		this.vjobId = id;
	}
	
	public void dispose() {
		print("vjob dispose");
		stopGateKeeper();
		msgCenter.stop();
	}
	
	public void startGateKeeper() {
		gkServer.start();
	}
	public void stopGateKeeper() {
		gkServer.stop();
	}
	private class VJobMessageCenter implements Runnable {
		private ServerSocket serverSocket = null;
		private volatile int port = 0;
		private InetAddress address = null;
		private Thread t = new Thread(this);
		
		public VJobMessageCenter() {
			try {
				serverSocket = new ServerSocket(0);
			} catch (IOException e) {}
			address = serverSocket.getInetAddress();
			port = serverSocket.getLocalPort();
			t.start();
		}
		public InetAddress getAddress() {
			return address;
		}
		public int getPort() {
			return port;
		}
		public void stop() {
			t.stop();
			if(!serverSocket.isClosed()) 
				try { serverSocket.close(); } catch(Exception e) {}
		}
		public void run() {
			while(true) {
				try {
					Socket conn = serverSocket.accept();
					new Thread(new VJobMessageProcessor(conn)).start();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public String getGKContact() {
		return gkServer.getContact();
	}
	
	/* parameters:
	 * -vjcaddress <host ip address> : the IP address of VJMCenter
	 * -vjcport <port>	: the listening port of VJMCenter
	 * -reservationid <id>	: 
	 * -requestid <id>		: the request id
	 */
	public static void main(String[] args) throws UnknownHostException {
		VJobExecute ve = VJobExecute.getInstance();
		
		for(int i = 0; i < args.length; i++) {
			if(args[i].equalsIgnoreCase("-vjcaddress")) {
				try {
					ve.setVJCAddress(InetAddress.getByName(args[++i]));
				} catch (Exception e) {
					System.err.println("Unknown VJMCenter Address.");;
					return;
				}
			} else if(args[i].equalsIgnoreCase("-vjcport")) {
				ve.setVJCPort(Integer.parseInt(args[++i]));
			} else if(args[i].equalsIgnoreCase("-reservationid")) {
				ve.setReservationHandler(Integer.parseInt(args[++i]));
			} else if(args[i].equalsIgnoreCase("-requestid")) {
				ve.setRequestId(Integer.parseInt(args[++i]));
			}
		}
		
		//ve.setVJCPort(38203);
		//ve.setVJCAddress(InetAddress.getLocalHost());
		print("paassed: vjcAddress = " + ve.getVJCAddress().getHostAddress() +
				"\nvjcport = " + ve.getVJCPort());
		
		new Thread(new VJobMessageProcessor(new VJobStartMessage())).start();
		
		ve.startGateKeeper();
		while(ve.getGKContact() == null);
		
		print("start gatekeeper, contact: " + ve.getGKContact());
		new Thread(new VJobMessageProcessor(new VJobAvailableMessage())).start();
	}
	private static void print(Object obj) {
		System.out.println(obj);
	}
	private static void debug(Object obj) {
		System.err.println(obj);
	}
}
